/**
 * 项目名：化工企业安全生产信息化管理平台
 * 日期：    2020-03-25 22:54:13
 * Copyright (c) 2015- -版权所有
 */

package com.joysuch.wwyt.bp.service.impl;

import cn.zlg.common.util.CollectionUtils;
import com.google.common.collect.Lists;
import com.joysuch.wwyt.bp.bean.BpAccidentCorrectiveMeasureDetailBean;
import com.joysuch.wwyt.bp.bean.BpAccidentDetailBean;
import com.joysuch.wwyt.bp.bean.BpAccidentEditBean;
import com.joysuch.wwyt.bp.bean.BpAccidentListBean;
import com.joysuch.wwyt.bp.bean.BpAccidentListBean.SearchBpAccident;
import com.joysuch.wwyt.bp.entity.BpAccident;
import com.joysuch.wwyt.bp.entity.BpAccidentCorrectiveMeasure;
import com.joysuch.wwyt.bp.entity.dsl.QBpAccident;
import com.joysuch.wwyt.bp.enums.AccidentType;
import com.joysuch.wwyt.bp.enums.BpAccidentAuditStates;
import com.joysuch.wwyt.bp.repository.BpAccidentDao;
import com.joysuch.wwyt.bp.repository.BpDepartDao;
import com.joysuch.wwyt.bp.service.BpAccidentCorrectiveMeasureService;
import com.joysuch.wwyt.bp.service.BpAccidentService;
import com.joysuch.wwyt.core.common.ajax.ResultBean;
import com.joysuch.wwyt.core.common.util.PageDataUtils;
import com.joysuch.wwyt.core.common.util.PageDataUtils.PageDataConvert;
import com.joysuch.wwyt.core.exception.BusinessRestrictionsException;
import com.joysuch.wwyt.core.repository.BaseTypeGroupItemDao;
import com.joysuch.wwyt.core.repository.BaseUserDao;
import com.joysuch.wwyt.core.service.BaseAttachmentRepositoryService;
import com.joysuch.wwyt.core.service.BizCodeGeneratorFacade;
import com.joysuch.wwyt.risk.repository.RiskDistrictDao;
import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Predicate;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.transaction.Transactional;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
@Transactional
public class BpAccidentServiceImpl implements BpAccidentService {

    @Autowired
    private BpAccidentDao dao;
    @Autowired
    private BaseTypeGroupItemDao baseTypeGroupItemDao;
    @Autowired
    private BaseUserDao baseUserDao;
    @Autowired
    private RiskDistrictDao riskDistrictDao;
    @Autowired
    private BpDepartDao bpDepartDao;
    @Autowired
    private BizCodeGeneratorFacade bizCodeGeneratorFacade;
    @Autowired
    private BaseAttachmentRepositoryService baseAttachmentRepositoryService;
    @Autowired
    private BpAccidentCorrectiveMeasureService bpAccidentCorrectiveMeasureService;

    @Override
    public BpAccident add(BpAccidentEditBean entity) {
        BpAccident content = new BpAccident();
        if (StringUtils.isNotBlank(entity.getCode())) {
            Assert.isTrue(dao.countOfCode(entity.getCode()) == 0, String.format("编号%s已经存在", entity.getCode()));
            content.setCode(entity.getCode());
        } else {
            content.setCode(bizCodeGeneratorFacade.shiGu());
        }
        if (entity.getAttachment() != null) {
            content.setAttachmentId(entity.getAttachment().getId());
        }
        if (entity.getAccidentChainFile() != null) {
            content.setAccidentChainFileId(entity.getAccidentChainFile().getId());
        }
        if (entity.getAccidentTreeAnalyseTableFile() != null) {
            content.setAccidentTreeAnalyseTableFileId(entity.getAccidentTreeAnalyseTableFile().getId());
        }
        if (entity.getFinalReportFile() != null) {
            content.setFinalReportFileId(entity.getFinalReportFile().getId());
        }
        BeanUtils.copyProperties(entity, content, "id", "code");
        content.setState((byte) 0);
        content.setAuditState(BpAccidentAuditStates.TO_AUDIT.getState());
        dao.save(content);
        return content;
    }

    @Override
    public void update(BpAccidentEditBean entity) {
        BpAccident content = dao.findById(entity.getId()).get();
        Assert.notNull(entity.getCode(), "编号不能为空");
        Assert.isTrue(dao.countOfCodeExcludeId(entity.getCode(), entity.getId()) == 0,
                String.format("编号%s已经存在", entity.getCode()));
        content.setCode(entity.getCode());
        if (entity.getAttachment() != null) {
            content.setAttachmentId(entity.getAttachment().getId());
        }
        if (entity.getAccidentChainFile() != null) {
            content.setAccidentChainFileId(entity.getAccidentChainFile().getId());
        }
        if (entity.getAccidentTreeAnalyseTableFile() != null) {
            content.setAccidentTreeAnalyseTableFileId(entity.getAccidentTreeAnalyseTableFile().getId());
        }
        if (entity.getFinalReportFile() != null) {
            content.setFinalReportFileId(entity.getFinalReportFile().getId());
        }
        BeanUtils.copyProperties(entity, content, "id", "code");
        dao.save(content);
        saveOrUpdateCorrectiveMeasures(content.getId(), entity.getCorrectiveMeasures());
    }

    private void saveOrUpdateCorrectiveMeasures(Long id,
                                                List<BpAccidentCorrectiveMeasureDetailBean> correctiveMeasures) {
        if (CollectionUtils.isEmpty(correctiveMeasures)) {
            bpAccidentCorrectiveMeasureService.deleteByAccidentId(id);
        } else {
            List<Long> existingIds = correctiveMeasures.stream().map(BpAccidentCorrectiveMeasureDetailBean::getId)
                    .filter(Objects::nonNull).collect(Collectors.toList());
            bpAccidentCorrectiveMeasureService.deleteByAccidentIdExcludeIds(id, existingIds);
            List<BpAccidentCorrectiveMeasure> measures = correctiveMeasures.stream().map(e -> {
                BpAccidentCorrectiveMeasure entity = null;
                if (e.getId() != null) {
                    entity = bpAccidentCorrectiveMeasureService.findById(e.getId());
                } else {
                    entity = new BpAccidentCorrectiveMeasure();
                }
                BeanUtils.copyProperties(e, entity);
                entity.setAccidentId(id);
                return entity;
            }).collect(Collectors.toList());
            bpAccidentCorrectiveMeasureService.saveAll(measures);
        }
    }

    @Override
    public Page<BpAccidentListBean> findByPage(Pageable page, SearchBpAccident condition) {
        page = PageDataUtils.addOrderByDesc(page, "createTime");
        Predicate predicate = prepareListSearchCondition(condition);

        Page<BpAccident> data = predicate == null ? dao.findAll(page) : dao.findAll(predicate, page);

        return PageDataUtils.convertPageData(data, new PageDataConvert<BpAccidentListBean, BpAccident>() {

            @Override
            public BpAccidentListBean convert(BpAccident f) {
                BpAccidentListBean bean = new BpAccidentListBean();
                BeanUtils.copyProperties(f, bean);
                bean.setReasonName(baseTypeGroupItemDao.getNameById(f.getReason()));
                bean.setReportorName(baseUserDao.getRealNameById(f.getReportorId()));
                bean.setRiskDistrictName(riskDistrictDao.getNameById(f.getRiskDistrictId()));
                bean.setCorrectiveInChargeUserName(baseUserDao.getRealNameById(f.getCorrectiveInChargeUserId()));
                bean.setDepartName(bpDepartDao.getNameById(f.getDepartId()));
                if (f.getAttachmentId() != null) {
                    bean.setAttachment(baseAttachmentRepositoryService.findByIdIntoBean(f.getAttachmentId()));
                }
                if (f.getAccidentChainFileId() != null) {
                    bean.setAccidentChainFile(
                            baseAttachmentRepositoryService.findByIdIntoBean(f.getAccidentChainFileId()));
                }
                if (f.getAccidentTreeAnalyseTableFileId() != null) {
                    bean.setAccidentTreeAnalyseTableFile(
                            baseAttachmentRepositoryService.findByIdIntoBean(f.getAccidentTreeAnalyseTableFileId()));
                }
                if (f.getFinalReportFileId() != null) {
                    bean.setFinalReportFile(baseAttachmentRepositoryService.findByIdIntoBean(f.getFinalReportFileId()));
                }
                //事故等级
                bean.setLevelName(AccidentType.getLevelName(f.getLevel()));
                bean.setCorrectiveMeasures(queryCorrectiveMeasures(f.getId()));
                bean.setAuditStateName(BpAccidentAuditStates.findNameByState(f.getAuditState()));
                return bean;
            }

        });
    }

    private Predicate prepareListSearchCondition(SearchBpAccident condition) {
        Predicate p = null;
        QBpAccident q = QBpAccident.bpAccident;
        if (condition.getReason() != null) {
            p = ExpressionUtils.and(p, q.reason.eq(condition.getReason()));
        }
        if (condition.getDepartId() != null) {
            p = ExpressionUtils.and(p, q.departId.eq(condition.getDepartId()));
        }
        if (condition.getState() != null) {
            p = ExpressionUtils.and(p, q.state.eq(condition.getState()));
        }
        if (!org.springframework.util.CollectionUtils.isEmpty(condition.getAuditStates())){
            p = ExpressionUtils.and(p, q.auditState.in(condition.getAuditStates()));
        }
        return p;
    }

    @Override
    public void delete(Long id) throws BusinessRestrictionsException {
        // 校验业务逻辑是否允许删除。如本数据被其他业务关联，删除后导致其他业务不可用。不能删除时将抛出业务异常
        checkBussinessRestrictions(id);
        dao.deleteById(id);
    }

    /**
     * 校验业务逻辑是否允许删除。如本数据被其他业务关联，删除后导致其他业务不可用
     *
     * @param id 要删除的业务ID
     */
    private void checkBussinessRestrictions(Long id)  {
        dao.findById(id).ifPresent(
                e -> Assert.isTrue(e.getState() == null || e.getState() == 0, "已发起报告的不能删除"));
    }

    @Override
    public BpAccident findById(Long id) {
        return dao.findById(id).orElse(null);
    }

    @Override
    public ResultBean setMeasure(BpAccidentCorrectiveMeasureDetailBean bean) {
        BpAccidentCorrectiveMeasure measure = bpAccidentCorrectiveMeasureService.findById(bean.getId());
        Assert.notNull(measure, "此数据不存在");
        BeanUtils.copyProperties(bean, measure);
        bpAccidentCorrectiveMeasureService.saveAll(Lists.newArrayList(measure));
        return ResultBean.defaultSuccessResult();
    }

    @Override
    public BpAccidentDetailBean getById(Long id) {
        BpAccident entity = findById(id);
        if (entity == null) {
            return null;
        }
        BpAccidentDetailBean bean = new BpAccidentDetailBean();
        BeanUtils.copyProperties(entity, bean);
        bean.setReasonName(baseTypeGroupItemDao.getNameById(entity.getReason()));
        bean.setReportorName(baseUserDao.getRealNameById(entity.getReportorId()));
        bean.setRiskDistrictName(riskDistrictDao.getNameById(entity.getRiskDistrictId()));
        bean.setCorrectiveInChargeUserName(baseUserDao.getRealNameById(entity.getCorrectiveInChargeUserId()));
        bean.setDepartName(bpDepartDao.getNameById(entity.getDepartId()));
        if (entity.getAttachmentId() != null) {
            bean.setAttachment(baseAttachmentRepositoryService.findByIdIntoBean(entity.getAttachmentId()));
        }
        if (entity.getAccidentChainFileId() != null) {
            bean.setAccidentChainFile(
                    baseAttachmentRepositoryService.findByIdIntoBean(entity.getAccidentChainFileId()));
        }
        if (entity.getAccidentTreeAnalyseTableFileId() != null) {
            bean.setAccidentTreeAnalyseTableFile(
                    baseAttachmentRepositoryService.findByIdIntoBean(entity.getAccidentTreeAnalyseTableFileId()));
        }
        if (entity.getFinalReportFileId() != null) {
            bean.setFinalReportFile(baseAttachmentRepositoryService.findByIdIntoBean(entity.getFinalReportFileId()));
        }
        bean.setCorrectiveMeasures(queryCorrectiveMeasures(id));
        bean.setAuditStateName(BpAccidentAuditStates.findNameByState(entity.getAuditState()));
        return bean;
    }

    private List<BpAccidentCorrectiveMeasureDetailBean> queryCorrectiveMeasures(Long id) {
        return bpAccidentCorrectiveMeasureService.queryDetailList(id);
    }

}
